home *** CD-ROM | disk | FTP | other *** search
- PAGE 63, 132
- Title Interupt support for the Hercules Graphics Card
-
-
- CSEG SEGMENT
- ORG 100H
- ASSUME CS:CSEG, DS:CSEG, SS:CSEG
- START: JMP SET_UP
-
- ;------------------------ routine ----------------------
- ROUTINE PROC FAR
- PUSHF
- PUSH ES
- PUSH DS
- PUSH SI
- PUSH DI
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- JMP SKIP_DATA
-
- ; data section
-
- Pos_X DW ?
- Pos_Y DW ?
- Pos_Err DW ?
-
- Neg_X DW ?
- Neg_Y DW ?
- Neg_Err DW ?
-
- Line_Err DW ?
-
- LENGTH DW ?
- Point_Type DB ?
-
- X1 DW ?
- Y1 DW ?
- X2 DW ?
- Y2 DW ?
- DeltaX DW ?
- DeltaY DW ?
- Ten DB 0Ah
-
- Function_Table DW 8 DUP(0)
-
- Active_page DB 0
-
- Segment_value DW ?
- Offset_Value DW ?
-
-
- ;
- ;++======================================================================++
- ;|| ||
- ;|| Draws the line given the present data ||
- ;|| ||
- ;++======================================================================++
- ;
- DrawIt PROC Near
- MOV AX, 0B000h
- MOV BH, Active_page
- CMP BH, 0
- JE Pg_0d
- MOV AX, 0B800h
-
- Pg_0d: MOV ES, AX
-
- MOV AX, Y2 ; see which is larger. if Y1 is larger,
- CMP AX, Y1 ; you have to swap the end points
- JNL No_Swap ; ( you always want to go up )
-
-
- MOV AX, Y1 ; put the first Y value into the AX register
- MOV BX, Y2 ; put the second Y value into the BX register
- MOV Y2, AX ; put the first Y value into the second Y
- MOV Y1, BX ; put the second Y value into the first Y
-
- MOV AX, X1 ; same as above for the X values
- MOV BX, X2
- MOV X2, AX
- MOV X1, BX
-
-
- No_Swap: MOV AX, X2 ; come up with the difference in X's
- SUB AX, X1
- MOV DeltaX, AX
-
- MOV AX, Y2 ; come up with the difference in Y's
- SUB AX, Y1
- MOV DeltaY, AX
- JNZ Not_Horiz ; if DeltaY is zero, the line is horizontal
- JMP Horiz
-
- Not_Horiz:
- CMP AX, DeltaX ; compare DeltaY to DeltaX
- JNE Not_Diag1 ; if they are equal, the slope is 1
- JMP Diag1
-
- Not_Diag1:
- XOR AX, 0FFFFh ; get negative DeltaY in AX
- INC AX
- CMP AX, DeltaX ; compare negative DeltaY to DeltaX
- JNE Not_Diag2 ; if they are equal, the slope is -1
- JMP Diag2
-
- Not_Diag2:
- CMP DeltaX, 0 ; compare DeltaX to zero
- JNE Not_Vert ; if there is no difference in X's, it's vert
- JMP Vert
-
- Not_Vert:
- JL Case_3_or_4 ; this line has a negative slope
-
- Case_1_or_2:
- XOR AX, 0FFFFh ; AX should still have -DeltaY
- INC AX ; so, make it positive
- CMP AX, DeltaX ; compare this to DeltaX
- JA Case2 ; if DeltaY > DeltaX the goto Case 2
-
- Case1: MOV DX, AX ; store the negative error correction
-
- MOV SI, DeltaX ; the length of the line
- SUB AX, SI ; Positive error = DeltaY - DeltaX
- MOV CX, AX ; store it
-
- MOV BX, X1 ; get the starting point
- MOV AX, Y1
-
- XOR DI, DI ; initialize the error register
-
- Plot_1: CALL Plot_pt
- CMP DI, 0 ; compare the error to zero
- JL Neg_err_1 ; if a negative error, jump pos err code
- ADD DI, CX ; add pos error correction
- INC AX ; next point is "up" and to the right
- INC BX
- JMP Chk_1 ; jump neg err code
- Neg_err_1:
- ADD DI, DX ; add neg error correction
- INC BX ; next point is to the right
-
- Chk_1: DEC SI ; decrement counter
- JNZ Plot_1 ; check to see if you are done
-
- JMP Plot_end_pts ; go to where you will plot the end points
-
-
-
-
- Case2: MOV SI, AX ; AX has DeltaX in it and that is the length
- MOV CX, DeltaX ; get DeltaX for Pos err correction
- SUB AX, CX ; DeltaY - DeltaX
- MOV DX, AX ; store the Neg err correction
-
- XOR CX, 0FFFFh ; Pos err cor is -DeltaX
- INC CX
-
- MOV BX, X1
- MOV AX, Y1
-
- XOR DI, DI
-
- Plot_2: CALL Plot_pt
- CMP DI, 0 ; compare the error to zero
- JL Neg_err_2 ; if a negative error, jump pos err code
- ADD DI, CX ; add pos error correction
- INC AX ; next point is "up" one point
- JMP Chk_2 ; jump neg err code
- Neg_err_2:
- ADD DI, DX ; add neg error correction
- INC AX ; next point is "up" and to the right
- INC BX ;
-
- Chk_2: DEC SI ; decrement counter
- JNZ Plot_2 ; check to see if you are done
-
- JMP Plot_end_pts ; go to where you will plot the end points
-
-
-
-
- Case_3_or_4:
- MOV AX, DeltaX ; DeltaX is negative. Invert it and add 1 for
- XOR AX, 0FFFFh ; 2's compliment (leave DeltaX alone use AX)
- INC AX
-
-
- CMP AX, DeltaY ; If DeltaY > DeltaX . . .
- JB Case4 ; this means that the slope is < -1
-
-
- Case3: MOV SI, AX ; AX has DeltaX in it and that is the length
- MOV CX, DeltaY ; get DeltaY for neg err correction
- MOV DX, CX ; store it
- SUB CX, AX ; calculate the pos err correction: Dy - Dx
-
- MOV BX, X1 ; set initial values
- MOV AX, Y1
-
- XOR DI, DI
-
- Plot_3: CALL Plot_pt
- CMP DI, 0 ; compare the error to zero
- JL Neg_err_3 ; if a negative error, jump pos err code
- ADD DI, CX ; add pos error correction
- INC AX ; next point is "up" and to the left
- DEC BX
- JMP Chk_3 ; jump neg err code
- Neg_err_3:
- ADD DI, DX ; add neg error correction
- DEC BX ; next point is "up" and to the left
-
- Chk_3: DEC SI ; decrement counter
- JNZ Plot_3 ; check to see if you are done
-
- JMP Plot_end_pts ; go to where you will plot the end points
-
-
-
-
-
- Case4: MOV SI, DeltaY ; the length of the line
- XOR AX, 0FFFFh ; AX had -DeltaX in it
- INC AX ; change it to DeltaX
- MOV CX, AX ; set the pos err correction register ( +Dx )
- ADD AX, SI ; calculate the neg err correction ( Dy + Dx )
- MOV DX, AX ; store it
-
- MOV BX, X1 ; set initial values
- MOV AX, Y1
-
- XOR DI, DI
-
- Plot_4: CALL Plot_pt
- CMP DI, 0 ; compare the error to zero
- JL Neg_err_4 ; if a negative error, jump pos err code
- ADD DI, CX ; add pos error correction
- INC AX ; next point is "up" one point
- JMP Chk_4 ; jump neg err code
- Neg_err_4:
- ADD DI, DX ; add neg error correction
- INC AX ; next point is "up" and to the right
- DEC BX ;
-
- Chk_4: DEC SI ; decrement counter
- JNZ Plot_4 ; check to see if you are done
-
- JMP Plot_end_pts ; go to where you will plot the end points
-
-
-
-
-
- Horiz: MOV SI, DeltaX ; set the length variable
- MOV BX, X1 ; set initial values
- MOV AX, Y1
- CMP SI, 0 ; check to see if the length var is neg
- JG Plot_H ; if not, skip making it neg
- XOR SI, 0FFFFh ; make SI ( = -DeltaX ) positive
- INC SI
-
- Plot_H: CALL Plot_pt ; plot the point
- INC BX ; move one pixel right
- DEC SI ; decrement the counter
- JNZ Plot_H ; if not done, go again
-
- JMP Plot_end_pts ; plot the end points of the line
-
-
-
- Vert: XOR AX, 0FFFFh ; AX already had -DeltaY,
- INC AX ; make it DeltaY and
- MOV SI, AX ; stick it into the length var
- MOV BX, X1 ; set initial values
- MOV AX, Y1
-
- Plot_V: CALL Plot_pt ; plot the point
- INC AX ; move one pixel right
- DEC SI ; decrement the counter
- JNZ Plot_V ; if not done, go again
-
- JMP Plot_end_pts ; plot the end points of the line
-
-
-
-
- Diag1: MOV SI, AX ; AX still has DeltaY in it
- MOV BX, X1 ; the starting point
- MOV AX, Y1
-
- Plot_D1: CALL Plot_pt
- INC AX ; next point is "up" and to the right
- INC BX
- DEC SI ; decrement the counter
- JNZ Plot_D1 ; if not done, go again
-
- JMP Plot_end_pts
-
-
-
- Diag2: XOR AX, 0FFFFh ; AX has -DeltaY in it, change its sign
- INC AX
- MOV SI, AX ; store it
- MOV BX, X1 ; initial point
- MOV AX, Y1
-
- Plot_D2: CALL Plot_pt
- INC AX ; next point is "up" and to the left
- DEC BX
- DEC SI ; decrement counter
- JNZ Plot_D2 ; if not done, go again
-
-
-
-
- Plot_end_pts:
- MOV AX, Y1 ; set up for plotting the 1st end pt
- MOV BX, X1
- CALL Plot_Pt ; plot 1st end pt
-
- MOV AX, Y2 ; set up for plotting the 2nd end pt
- MOV BX, X2
- CALL Plot_Pt
-
- RET
-
- DrawIt ENDP ; done here
-
-
-
-
-
-
- ;
- ;++======================================================================++
- ;|| ||
- ;|| Plots a point at (BX,AX) if possible using Line_Type ||
- ;|| ||
- ;++======================================================================++
- ;
- Plot_Pt PROC Near
- PUSH AX ; save the values of X & Y
- PUSH BX
- PUSH CX
-
- CALL AddrHGC ; get the offset in the buffer
- CMP AX, 1000h ; check for an error being returned from
- JNE No_Plot ; if an error was detected, get out
-
- MOV CH, 1 ; bit to or into the byte
- SHL CH, CL ; move the bit into position
- CMP Point_Type, 2 ;
- JB Or_Point ; if plotting a line...
- JA Del_Point ; if erasing a line...
-
- XOR ES:[BX], CH ; xor the line
- JMP No_Plot
-
- Or_Point:
- OR ES:[BX], CH ; set the bit in the video buffer
- JMP No_Plot
-
- Del_Point:
- XOR CH, 0FFFFh ; reverse the bits
- AND ES:[BX], CH ; erase the bit
-
- No_Plot: POP CX ; CX was altered, restore it
- POP BX ; get the X value back
- POP AX ; get the Y value back
-
- RET
-
- Plot_Pt ENDP
-
-
-
-
-
- ;
- ; in: AX = y
- ; BX = x <--------------------+
- ; |
- ; out: AX = 1000 if value is OK or x if bad
- ; BX = byte offset in buffer
- ; CL = nuber of bits to shift left
- ;
-
- AddrHGC PROC Near
-
- CMP AX, 0 ; is the y value too small?
- JL DONE ; if so, get out of the procedure
- CMP AX, 347 ; is the y value too large?
- JG DONE ; if so, get out of the procedure
- CMP BX, 0 ; is the x value too small?
- JL DONE ; if so, get out of the procedure
- CMP BX, 719 ; is the x value too large?
- JG DONE ; if not, get out
-
- MOV CL, BL ; CL = low order byte of x
- SHR AX, 1 ; AX = y / 2
- RCR BX, 1 ; BX = 8000h * (y&1) + x/2
- SHR AX, 1 ; AX = y / 4
- RCR BX, 1 ; BX = 4000h * (y&3) + x/4
- SHR BX, 1 ; BX = 2000h * (y&3) + x/8
- MOV AH, 90 ; bytes per line (decimal)
- MUL AH ; AX = bytes per line * (y/4)
- ADD BX, AX ; BX = 2000h * (y&3) + x/8 +
- ; bytes per line * (y/4)
-
- AND CL, 7 ; CL = x & 7
- XOR CL, 7 ; CL = number of bits to shift left
- MOV AX, 1000h ; AH = unshifted bit mask
-
- DONE: RET
-
- AddrHGC ENDP
-
-
-
-
- ;
- ;++======================================================================++
- ;|| ||
- ;|| Turns on the HERCULES graphics mode ||
- ;|| ||
- ;++======================================================================++
- ;
- Graphics_on PROC Near
-
- MOV AL, 02Ah ; graphics mode (Page 0)
-
- AND DH, 01 ; get visible page from the instruction byte
- JZ Pg_0g ; if it is page 0, don't change now
- MOV AL, 0AAh ; graphics mode (Page 1)
-
- Pg_0g: MOV DX, 03B8h ; HGC mode control reister
- OUT DX, AL ; set to graphics mode
-
- MOV AL, 03h ; code to enable graphics
- MOV DX, 03BFh ; HGC config switch register
- OUT DX, AL ; enable graphics
-
- RET
-
- Graphics_on ENDP
-
-
-
-
- ;
- ;++======================================================================++
- ;|| ||
- ;|| Turns off the HERCULES graphics mode ||
- ;|| ||
- ;++======================================================================++
- ;
- Text_on PROC Near
-
- MOV AL, 028h ; text mode (page 0)
-
- AND DH, 01 ; get visible page from instruction byte
- JZ Pg_0 ; don't make it page 1 if page 0
- MOV AL, 0A8h ; text mode (page 1)
-
- Pg_0: MOV DX, 03B8h ; HGC mode control reister
- OUT DX, AL ; set to graphics mode
-
- MOV AL, 03h ; code to enable HGC
- MOV DX, 03BFh ; HGC config switch register
- OUT DX, AL ; enable graphics
-
- RET
-
- Text_on ENDP
-
-
-
-
- ;
- ;++======================================================================++
- ;|| ||
- ;|| plot a point on the graphics page ||
- ;|| ||
- ;++======================================================================++
- ;
- Point PROC near
- AND DH, 03 ; mask off the type of point
- MOV Point_type, DH ; set the variable
-
- MOV CX, ES:[BX] ; get the X value of the point
- ADD BX, 2 ; move past the data word
-
- MOV DX, ES:[BX] ; get the Y value of the point
- ADD BX, 2 ; move pointer past the data word
-
- MOV Offset_value, BX ; save current value
-
- MOV AX, 0B000h ; default graphics page ( page 0 )
- MOV BH, Active_page ; get the number of the active page
- CMP BH, 0 ; check to see if page 0 IS the active page
- JE Pg_0p ; if so, don't change it now
- MOV AX, 0B800h ; if not, do change it to page 1
-
- Pg_0p: MOV ES, AX ; plot_pt needs this
-
- MOV BX, CX ; BX is where the procedure expects the
- ; X value of the point
- MOV AX, DX ; AX is where the procedure expects the
- ; Y value of the point
-
- CALL Plot_Pt ; call the procedure to plot the point
-
- RET ; you're done here
- Point ENDP
-
-
-
-
-
- ;
- ;++======================================================================++
- ;|| ||
- ;|| plot a line on the graphics page ||
- ;|| ||
- ;++======================================================================++
- ;
- Line PROC near
- MOV CX, ES:[BX] ; get the first end point's X value
- MOV X1, CX ; store the value
- ADD BX, 2 ; mov the pointer past the word
-
- MOV CX, ES:[BX] ; get the 1st pt's Y value
- MOV Y1, CX ; store it
- ADD BX, 2
-
- MOV CX, ES:[BX] ; 2nd pt's X value
- MOV X2, CX
- ADD BX, 2
-
- MOV CX, ES:[BX] ; 2nd pt's Y value
- MOV Y2, CX
- ADD BX, 2
-
- MOV Offset_value, BX ; store current value of my IR
-
- AND DH, 03 ; get the line type
- MOV Point_type, DH ;
-
- CALL Drawit ; call the procedure to draw the line
-
- RET ; you're done
- Line ENDP
-
-
-
-
- ;
- ;++======================================================================++
- ;|| ||
- ;|| set the active page variable ||
- ;|| (needed by the plot_pt proc) ||
- ;|| ||
- ;++======================================================================++
- ;
- act_page PROC near
- AND DH, 01 ; the only pages are 0 and 1 & the LSB
- MOV Active_page, DH ; gives the page
- RET
- act_page ENDP
-
-
-
-
-
- ;
- ;++======================================================================++
- ;|| ||
- ;|| clears the given page (graphics) ||
- ;|| ||
- ;++======================================================================++
- ;
- Clear_page PROC near
- MOV AX, 0B000h ; start of video buffer
-
- AND DH, 01 ; get the active page number
- JE Clr_pg_1 ; if it is zero, you don't need to change AX
- MOV AX, 0B800h ; second page
-
- Clr_pg_1:MOV ES, AX ; set base value
-
- XOR DI, DI ; reset offset
- XOR AX, AX ; value to put in buffer ( AX = 0 )
- MOV CX, 8000H ; number of bytes to fill
- REP STOSW ; repeat storing value in memory
-
- RET
- Clear_page ENDP
-
-
-
- ;
- ;++======================================================================++
- ;|| ||
- ;|| fills the given page (graphics) ||
- ;|| ||
- ;++======================================================================++
- ;
- Fill_page PROC near
- MOV CX, ES:[BX] ; get the value to fill the buffer
- ADD BX, 2 ; increment the instruction pointer
- MOV Offset_value, BX ; store the pointer
-
- MOV AX, 0B000h ; start of video buffer
-
- AND DH, 01 ; get the active page number
- JE Fil_pg_1 ; if it is zero, you don't need to change AX
- MOV AX, 0B800h ; second page
-
- Fil_pg_1:MOV ES, AX ; set base value
-
- XOR DI, DI ; reset offset
-
- MOV AX, CX ; value to put in buffer ( AX = 0 )
- MOV CX, 8000H ; number of bytes to fill
- REP STOSW ; repeat storing value in memory
-
- RET
- Fill_page ENDP
-
-
-
-
- ;
- ;++======================================================================++
- ;|| ||
- ;|| This is the error return function ||
- ;|| ||
- ;++======================================================================++
- ;
- Err_in_fn: POP AX ; the calling value of the AX register is
- ; on top of the stack. get it off.
- MOV AH, 0FFh ; signify an error return
- MOV AL, DH ; return erroneous function
- JMP Err_exit ; get out while you still can
-
-
-
- ;
- ;++======================================================================++
- ;|| ||
- ;|| This is the main loop of the code ||
- ;|| ||
- ;++======================================================================++
- ;
- SKIP_DATA: MOV CX, CS ; set DS to the same as CS
- MOV DS, CX
-
- MOV Segment_value, AX ; save these important values
- MOV Offset_value, BX
-
- MOV ES, AX ; move data segment value into ES
-
- Go_again: MOV DH, ES:[BX] ; load the function byte
- INC BX ; increment my program counter
- MOV Offset_value, BX ; save program counter
- CMP DH, 0 ; compare it to 0 to see if you are done
- JE Quit_int ; if equal, get out
- CMP DH, 80h ; see if the function # is too high
- JAE Err_in_fn ; if so, go tell the user
- CMP DH, 10h ; see if the function # is too low
- JB Err_in_fn ; if so, go tell the user
-
- MOV CL, 3 ; bits to shift left (to find fn in table)
- MOV DL, DH ;
- XOR DH, DH
- MOV SI, DX ; copy function byte for manipulation
- SHR SI, CL ; shift byte (divide it by 8)
- AND SI, 0Eh ; mask off value (offset into the table)
- MOV DH, DL ; some of the fns require DH to have the
- ; instruction byte
-
- CALL Function_table[SI] ; jump to funcion offset in the table
-
- MOV BX, Segment_value ; get the segment value
- MOV ES, BX ; set the ES register to the proper segment
-
- MOV BX, Offset_value ; get pointer to next instruction
- JMP Go_again ; start over
-
-
- Quit_int: POP AX
- Err_exit: POP BX
- POP CX
- POP DX
- POP DI
- POP SI
- POP DS
- POP ES
- POPF
- IRET
- FINISH EQU $
- ROUTINE ENDP
-
- ;----------------------- set up -----------------------
- SET_UP: LEA BX, Function_Table ; set up fuction offset table
-
- LEA CX, Graphics_on
- MOV [BX+2], CX
-
- LEA CX, Text_on
- MOV [BX+4], CX
-
- LEA CX, Point
- MOV [BX+6], CX
-
- LEA CX, Line
- MOV [BX+8], CX
-
- LEA CX, Act_page
- MOV [BX+10], CX
-
- LEA CX, Clear_page
- MOV [BX+12], CX
-
- LEA CX, Fill_page
- MOV [BX+14], CX
-
- LEA DX, Strt_msg
- MOV AH, 9
- INT 21H
-
- MOV DX, OFFSET ROUTINE ; start of routine
- MOV AL, 70H ; what interupt I plan to use
- MOV AH, 25H ; DOS function to set the int vector
- INT 21H ; set the vector
-
- LEA DX, FINISH ; end of resident routine
- INT 27H ; quit and routine stays resident
-
- strt_msg DB 13, 10, '╒══════════════════════════════════════════╕'
- DB 13, 10, '│ │'
- DB 13, 10, '│ Hercules video support now resident. │'
- DB 13, 10, '│ │'
- DB 13, 10, '│ INT 70h │'
- DB 13, 10, '│ by │'
- DB 13, 10, '│ │'
- DB 13, 10, '│ Ted O''Connor │'
- DB 13, 10, '│ │'
- DB 13, 10, '╘══════════════════════════════════════════╛'
-
- DB 13, 10, 10, '$'
-
- CSEG ENDS
- END START
- END